use common::{
    base::status::Status,
    protocol::{protocol_v1::ProtocolV1Writer, MsgType},
    serial,
    service::{sys_service_api::StringResponse, ServiceKey},
    utils::string_utils,
};
use tracing::info;

use crate::{application::Application, service::service::Service};

use super::{
    get_local_service, pack_and_return_bool, pack_and_return_error, pack_and_return_message,
    pack_and_return_success, XPORT_SERVICE_KEY,
};

pub extern "C" fn is_file_exist(service_id: i64, request_id: i64, filename: *const u8, len: u32) {
    let slice = unsafe { std::slice::from_raw_parts(filename, len as usize) };

    let file_path = serial::read_string(slice);

    tokio::spawn(async move {
        //
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();
        let file_manager = Application::get_file_manager();

        let is_exist = file_manager
            .is_file_exist(&local_service.dxc_name(), &file_path)
            .await;

        pack_and_return_bool(request_id, local_service.get_service_key(), is_exist);
    });
}

pub extern "C" fn is_dir_exist(service_id: i64, request_id: i64, filename: *const u8, len: u32) {
    let slice = unsafe { std::slice::from_raw_parts(filename, len as usize) };

    let file_path = serial::read_string(slice);

    tokio::spawn(async move {
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();

        let file_manager = Application::get_file_manager();

        let is_exist = file_manager
            .is_dir_exist(&local_service.dxc_name(), &file_path)
            .await;

        pack_and_return_bool(request_id, local_service.get_service_key(), is_exist);
    });
}

pub extern "C" fn create_dir(service_id: i64, request_id: i64, dir_path: *const u8, len: u32) {
    let slice = unsafe { std::slice::from_raw_parts(dir_path, len as usize) };

    let file_path = serial::read_string(slice);

    tokio::spawn(async move {
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();

        let file_manager = Application::get_file_manager();

        let is_succeed = file_manager
            .create_dir(&local_service.dxc_name(), &file_path)
            .await;

        if is_succeed {
            pack_and_return_success(request_id, local_service.get_service_key());
        } else {
            pack_and_return_error(
                request_id,
                local_service.get_service_key(),
                Status::error(String::default()),
            );
        }
    });
}

pub extern "C" fn create_file(service_id: i64, request_id: i64, filename: *const u8, len: u32) {
    let slice = unsafe { std::slice::from_raw_parts(filename, len as usize) };

    let file_path = serial::read_string(slice);

    tokio::spawn(async move {
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();      

        let file_manager = Application::get_file_manager();

        let is_succeed = file_manager
            .create_file(&local_service.dxc_name(), &file_path)
            .await;

        if is_succeed {
            pack_and_return_success(request_id, local_service.get_service_key());
        } else {
            pack_and_return_error(
                request_id,
                local_service.get_service_key(),
                Status::error(String::default()),
            );
        }
    });
}
//
pub extern "C" fn write_file(
    service_id: i64,
    request_id: i64,
    filename: *const u8,
    len: u32,
    content: *const u8,
    content_len: u32,
) {
    //
    let slice = unsafe { std::slice::from_raw_parts(filename, len as usize) };
    let file_path = serial::read_string(slice);
    //
    let content = string_utils::raw_to_string(content, content_len);
    //
    tokio::spawn(async move {
        //
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();

        let file_manager = Application::get_file_manager();

        let ret = file_manager
            .write_content_to_file(&local_service.dxc_name(), &file_path, &content)
            .await;

        if ret.is_ok() {
            pack_and_return_success(request_id, local_service.get_service_key());
        } else {
            pack_and_return_error(
                request_id,
                local_service.get_service_key(),
                Status::error(ret.err().unwrap().to_string()),
            );
        };
    });
}

pub extern "C" fn get_md5(service_id: i64, request_id: i64, file_path: *const u8, len: u32) {
    //
    let slice = unsafe { std::slice::from_raw_parts(file_path, len as usize) };
    let file_path = serial::read_string(slice);
    tokio::spawn(async move {
        //
        let local_service = get_local_service(service_id, request_id, false).await;
        if local_service.is_none() {
            return;
        }
        let local_service = local_service.unwrap();
        
        let file_manager = Application::get_file_manager();
        let ret = file_manager.get_md5(&file_path);
        if let Ok(md5) = ret {
            let mut result = StringResponse::default();

            result.value = md5;

            pack_and_return_message(request_id, local_service.get_service_key(), result)
        } else {
            pack_and_return_error(
                request_id,
                local_service.get_service_key(),
                Status::error(ret.err().unwrap().to_string()),
            );
        }
    });
}


pub extern "C" fn get_dxc_dsl(service_id: i64, request_id: i64, file_path: *const u8, len: u32) {
  //
  let slice = unsafe { std::slice::from_raw_parts(file_path, len as usize) };
  let file_path = serial::read_string(slice);
  tokio::spawn(async move {
      //
      let local_service = get_local_service(service_id, request_id, false).await;
      if local_service.is_none() {
          return;
      }
      let local_service = local_service.unwrap();

      let file_manager = Application::get_file_manager();

      let ret = file_manager.get_dxc_dsl(&file_path);

      if let Ok(dxc_info) = ret {
          pack_and_return_message(request_id, local_service.get_service_key(), dxc_info)
      } else {
          pack_and_return_error(
              request_id,
              local_service.get_service_key(),
              Status::error(ret.err().unwrap().to_string()),
          );
      }
  });
}
